package com.example.nettydemo.server;

import com.example.nettydemo.config.GameConfig;
import com.example.nettydemo.game.Room;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author WZW
 * @date 2020/4/24
 */
public class NettyChannelHandlerPool {
    //保存游戏房间
    private static final Map<String, Room> roomMap = new ConcurrentHashMap<>();
    //保存房间中的玩家
    private static final Map<String, Set<String>> roomIdGuidSetMap = new ConcurrentHashMap<>();
    //保存连接用户的唯一标识及用户使用的ChannelId，这里用map存储，也可以存储在redis中
    private static final Map<String, ChannelId> guidChannelIdMap = new ConcurrentHashMap<>();

    public static Map<String, Room> getRoomMap() {
        return roomMap;
    }

    public static Map<String, Set<String>> getRoomIdGuidSetMap() {
        return roomIdGuidSetMap;
    }

    public static Map<String, ChannelId> getGuidChannelIdMap() {
        return guidChannelIdMap;
    }

    //保存所有的Channel
    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    public static void putChannel(String guid, ChannelId channelId) {
        guidChannelIdMap.put(guid, channelId);
    }

    public static ChannelId getChannel(String guid) {
        return guidChannelIdMap.get(guid);
    }

    public static void removeChannel(String guid) {
        if (!guidChannelIdMap.containsKey(guid)) {
            return;
        }
        ChannelId channelId = getChannel(guid);
        Channel channel = channelGroup.find(channelId);
        if (channel != null) {
            channelGroup.remove(channel);
        }
        System.out.println("从Map中删除" + guid);
        guidChannelIdMap.remove(guid);
    }

    public static int getOnlineCount() {
        return guidChannelIdMap.size();
    }

    /**
     * 保存房间
     *
     * @param roomId 房间Id
     * @param room   房间
     */
    public static void putRoom(String roomId, Room room) {
        roomMap.put(roomId, room);
    }

    /**
     * 房间是否存在
     *
     * @param roomId 房间id
     * @return true : 存在，false ：不存在
     */
    public static boolean isRoomExist(String roomId) {
        return roomMap.containsKey(roomId);
    }

    /**
     * 获取房间
     *
     * @param roomId 房间id
     * @return 房间
     */
    public static Room getRoom(String roomId) {
        return roomMap.get(roomId);
    }

    /**
     * 创建或获取房间。房间不存在就创建并返回，房间存在就直接返回
     *
     * @param roomId     房间id
     * @param gameConfig 游戏配置
     * @return 房间
     */
    public static Room createOrGetRoom(String roomId, GameConfig gameConfig) {
        if (isRoomExist(roomId)) {
            //存在
            return NettyChannelHandlerPool.getRoom(roomId);
        } else {
            //不存在，创建并开始
            Room room = new Room(roomId, gameConfig);
            //开始游戏
            room.startGame();
            //将房间保存
            putRoom(roomId, room);
            return room;
        }
    }

    /**
     * 将玩家添加到对应的房间
     *
     * @param roomId 房间Id
     * @param guid   玩家Id
     */
    public static void putRoomGuid(String roomId, String guid) {
        //先删掉之前保存的guid
        removeGuid(guid);
        Set<String> guidSet;
        if (!roomIdGuidSetMap.containsKey(roomId)) {
            //房间不存在
            guidSet = new HashSet<>();
        } else {
            //房间存在
            guidSet = roomIdGuidSetMap.get(roomId);
        }
        guidSet.add(guid);
        roomIdGuidSetMap.put(roomId, guidSet);
    }

    /**
     * 获取指定房间中所有的玩家id
     *
     * @param roomId 房间id
     * @return 玩家guid的集合
     */
    public static Set<String> getGuidSet(String roomId) {
        return roomIdGuidSetMap.get(roomId);
    }

    /**
     * 获取所有的guid
     *
     * @return guidSet
     */
    public static Set<String> getAllGuidSet() {
        return guidChannelIdMap.keySet();
    }

    public static void removeRoom(String roomId) {
        Room room = roomMap.get(roomId);
        room.setGameOver(true);
        roomMap.remove(roomId);
        roomIdGuidSetMap.remove(roomId);
//        room = null;
    }

    /**
     * 从map中删除guid，玩家离线时调用
     */
    public static void removeGuid(String guid) {
        Set<String> roomIdSet = roomIdGuidSetMap.keySet();
        Set<String> deleteRoomIdSet = new HashSet<>();
        for (String roomId : roomIdSet) {
            Set<String> guidSet = roomIdGuidSetMap.get(roomId);
            guidSet.remove(guid);
            if (guidSet.size() == 0) {
                deleteRoomIdSet.add(roomId);
            }
        }
        deleteRoomIdSet.forEach(NettyChannelHandlerPool::removeRoom);
    }

}
